# tell/callback.py
#
#

"""

    W E L C O M E  T O  T E L L !!!

    -=-

    (this code is best enjoyed on a wide screen)

"""

## tell imports 

from tell import O
from .utils import get_name
from .errors import NoArgument, AlreadyThere

## basic imports

import logging
import time

## Callback class

class Callback(O):

    ## register methods - adding objects to a list in the O object

    def get_keys(self, type, want=""):
        result = []
        for key in self.keys():
            if type and type not in str(key): continue
            if want and want not in str(key): continue
            result.append(key)
        for item in result: yield item

    def get_reg(self, type, want=""):
        result = []
        for key in self.keys():
            if type and type not in str(key): continue
            if want and want not in str(key): continue
            result.append(self[key])
        for item in result: yield item

    def register(self, *args, **kwargs):
        """ add an O to this one. """   
        if len(args) != 3: raise NoArgument(str(args))
        if type(args[2]) == list: target = args[2]
        else: target = [args[2], ]
        for t in target:
            thing = O()
            thing.otype = args[0]
            thing.name = args[1]
            thing.func = t
            target = "%s.%s.%s" % (thing.otype, thing.name, get_name(thing.func))
            logging.warn("reg.%s" % target)
            thing.target = target
            self[target] = thing
        return self

    ## power core dispatching stuff - running code on the O data

    def run_cb(self, *args, **kwargs):
        if args: target = args[0]
        else: target = self
        for call in self.get_reg("cb", want=target.cbtype):
            if not call: continue
            callback = call.func
            try: pre = getattr(callback, "pre")
            except AttributeError: pre = None ; self.do_status = True
            if pre and not pre(target): logging.debug("pre failed") ; continue
            target.status[str(time.ctime(time.time()))] = callback(target)
            target.target = call.target
            try: post = callback.post
            except AttributeError: self.do_status = True ; continue
            post(target)
        return target

    def dispatch(self, *args, **kwargs):
        if args: target = args[0]
        else: target = self
        if target.hascc():
            target.want_dispatch = True
            commands = self.get_reg("cmnd", want=target.cmnd)
            for cmnd in commands:
                command = cmnd.func
                try: pre = getattr(command, "pre")
                except AttributeError: pre = None 
                if pre and not pre(target): logging.info("pre failed") ; return
                status = command(target)
                self.status[str(time.ctime(time.time()))] = status or "ok"
                try: post = getattr(command, "post")
                except AttributeError: post = None  
                if post: post(target)
        return target

    def execute(self, *args, **kwargs):
        if args: target = args[0]
        else: target = self
        try: func = getattr(target, "func")
        except (AttributeError, NoAttribute): func = None
        if not func: raise NoFunc() 
        try: pre_func = getattr(func, "pre")
        except AttributeError: pre_func = None 
        if pre_func and not pre_func(target): logging.info("pre failed") ; return
        status = func(target)
        self.status[str(time.ctime(time.time()))] = status or "ok"
        try: post_func = getattr(func, "post")
        except AttributeError: post_func = None  
        if post_func: post_func(target)
        target.done()
        return target


#### C O M M E N T  -=-  S E C T I O N

""" please write comments on changes you made below, so we can get log of things added/changed. """

## BHJTW 27-11-2012 initial import 
